﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;

namespace Hx.Infrastructure.Services
{
    public sealed class ServiceLocator
    {
        private static readonly ServiceLocator ServiceLocatorinstance = new ServiceLocator();
        private readonly IUnityContainer _container;

        private ServiceLocator()
        {
            var section = ConfigurationManager.GetSection("unity");
            var uSection = section as UnityConfigurationSection;
            _container = new UnityContainer();
            if (uSection != null)
                uSection.Configure(_container);
        }

        /// <summary>
        /// 实例
        /// </summary>
        public static ServiceLocator Instance
        {
            get { return ServiceLocatorinstance; }
        }

        /// <summary>
        /// Gets the resolver overrides.
        /// </summary>
        /// <param name="overridedArguments">The overrided arguments.</param>
        /// <returns>IEnumerable&lt;ResolverOverride&gt;.</returns>
        private IEnumerable<ResolverOverride> GetResolverOverrides(object overridedArguments)
        {
            var overrides = new List<ParameterOverride>();
            var argumentsType = overridedArguments.GetType();
            argumentsType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                .ToList()
                .ForEach(property =>
                {
                    var propertyValue = property.GetValue(overridedArguments, null);
                    var propertyName = property.Name;
                    overrides.Add(new ParameterOverride(propertyName, propertyValue));
                });
            return overrides;
        }

        /// <summary>
        /// 获取服务
        /// </summary>
        /// <typeparam name="T">服务类型</typeparam>
        public T GetService<T>()
        {
            return _container.Resolve<T>();
        }

        /// <summary>
        /// 获取服务
        /// </summary>
        /// <typeparam name="T">服务类型</typeparam>
        /// <param name="name">服务名称</param>
        public T GetService<T>(string name)
        {
            return _container.Resolve<T>(name);
        }

        /// <summary>
        /// 获取服务
        /// </summary>
        /// <typeparam name="T">服务类型</typeparam>
        /// <param name="overridedArguments">The overrided arguments.</param>
        public T GetService<T>(object overridedArguments)
        {
            var overrides = GetResolverOverrides(overridedArguments);
            return _container.Resolve<T>(overrides.ToArray());
        }

        /// <summary>
        /// 获取服务
        /// </summary>
        /// <param name="serviceType">服务类型</param>
        public object GetService(Type serviceType)
        {
            return _container.Resolve(serviceType);
        }

        /// <summary>
        /// 获取服务
        /// </summary>
        /// <param name="serviceType">服务类型</param>
        /// <param name="overridedArguments">The overrided arguments.</param>
        public object GetService(Type serviceType, object overridedArguments)
        {
            var overrides = GetResolverOverrides(overridedArguments);
            return _container.Resolve(serviceType, overrides.ToArray());
        }

        /// <summary>
        /// 返回所有注册的服务实例
        /// </summary>
        /// <typeparam name="T">服务类型</typeparam>
        public IEnumerable<T> ResolveAll<T>()
        {
            return _container.ResolveAll<T>();
        }

        public void RegisterComponent(string service, string instance)
        {
            var fromType = Type.GetType(service);
            var toType = Type.GetType(instance);
            Debug.WriteLine("Service name:" + service);
            Debug.WriteLine("Instance name:" + instance);
            _container.RegisterType(fromType, toType);
        }

        /// <summary>
        /// 注册组件
        /// </summary>
        public void RegisterComponent(string name, string service, string instance)
        {
            var fromType = Type.GetType(service);
            var toType = Type.GetType(instance);
            _container.RegisterType(fromType, toType, name);
        }
    }
}
